package net.chrisrichardson.ec2deployer.applications

import net.chrisrichardson.ec2deployer.applications.WebApp
import groovy.mock.interceptor.MockFor
import net.chrisrichardson.ec2deployer.core.EC2Server
import net.chrisrichardson.ec2deployer.core.S3Synchronizer
import net.chrisrichardson.ec2deployer.core.AWSProperties

class WebAppTest extends GroovyTestCase {

    MockFor mockTomcatServer
    MockFor mockEc2Server
    MockFor mockS3Synchronizer

    public void setUp() {
        mockTomcatServer = new MockFor(TomcatServer)
        mockEc2Server = new MockFor(EC2Server)
        mockS3Synchronizer = new MockFor(S3Synchronizer)
    }

    public void testS3BucketOfNonS3Url() {
        WebApp webApp = new WebApp("/home/users/foo/myWebApp", "foo")
        assertEquals "foo-tmp-war", webApp.s3Bucket
    }

    public void testS3BucketOfS3UrlWithoutPath() {
        WebApp webApp = new WebApp("s3://myBucket", "foo")
        assertEquals "myBucket", webApp.s3Bucket
    }

    public void testS3BucketOfS3UrlWithPath() {
        WebApp webApp = new WebApp("s3://myBucket/somepath", "foo")
        assertEquals "myBucket", webApp.s3Bucket
    }

    public void testSubDirectoryOfNonS3Url() {
        WebApp webApp = new WebApp("/home/users/foo/myWebApp", "foo")
        assertEquals "/myWebApp", webApp.subDirectory
    }

    public void testSubDirectoryOfNonS3UrlOnWindows() {
        WebApp webApp = new WebApp("c:\\home\\users\\foo\\myWebApp", "foo")
        assertEquals "/myWebApp", webApp.subDirectory
    }

    public void testSubDirectoryOfS3UrlWithoutPath() {
        WebApp webApp = new WebApp("s3://myBucket", "foo")
        assertEquals "", webApp.subDirectory
    }

    public void testSubDirectoryOfS3UrlWithPath() {
        WebApp webApp = new WebApp("s3://myBucket/somepath", "foo")
        assertEquals "/somepath", webApp.subDirectory
    }
    /*
    public void testUpdateWarRootNonS3Url() {
        WebApp webApp = new WebApp("/home/users/foo/myWebApp", "ROOT")

        mockEc2Server.demand.getAwsProperties { new AWSProperties(new Properties())}
        mockS3Synchronizer.demand.downloadFromS3 {host, String bucketPrefix, String bucket, String dir ->
            assertEquals "ROOT-tmp-war", bucket
            assertEquals "/tmp/ROOT-tmp-war", dir
        }

        mockEc2Server.demand.ssh {cmd ->
            assertEquals "mkdir -p /usr/catalina.home/deployments/ROOT /usr/catalina.home.other/conf/Catalina/localhost", cmd
        }

        mockEc2Server.demand.ssh {cmd ->
            assertEquals "rsync --del -u -v -r  /tmp/ROOT-tmp-war/myWebApp/ /usr/catalina.home/deployments/ROOT", cmd
        }
        mockEc2Server.demand.ssh {cmd, input ->
            assertEquals "cat > /usr/catalina.home.other/conf/Catalina/localhost/ROOT.xml", cmd
            assertEquals """
<Context docBase="/usr/catalina.home/deployments/ROOT">
</Context>
""", input
        }

        mockEc2Server.demand.ssh {cmd ->
                assertEquals "rm -fr /usr/catalina.home.other/webapps/ROOT", cmd
        }

        mockEc2Server.use {
            EC2Server ec2Server = new EC2Server()

            mockTomcatServer.demand.getHost { ec2Server }
            mockTomcatServer.demand.getCatalinaHome { "/usr/catalina.home" }
            mockTomcatServer.demand.getCatalinaHomeOther { "/usr/catalina.home.other" }
            mockTomcatServer.demand.getCatalinaHomeOther { "/usr/catalina.home.other" }
            mockTomcatServer.demand.getCatalinaHomeOther { "/usr/catalina.home.other" }

            mockS3Synchronizer.use {
                mockTomcatServer.use {
                    TomcatServer tomcatServer = new TomcatServer()
                    webApp.updateTomcat(tomcatServer, "")
                }
            }
        }
    }
    */
    public void testUpdateWarRootNonS3Url() {
        WebApp webApp = new WebApp("/home/users/foo/myWebApp", "ROOT")

        mockEc2Server.demand.getAwsProperties { new AWSProperties(new Properties())}
        mockS3Synchronizer.demand.downloadFromS3 {host, String bucketPrefix, String bucket, String dir ->
            assertEquals "ROOT-tmp-war", bucket
            assertEquals "/tmp/ROOT-tmp-war", dir
        }


        mockEc2Server.demand.ssh {cmd ->
            assertEquals "rsync --del -u -v -r  /tmp/ROOT-tmp-war/myWebApp/ /usr/catalina.home/webapps/ROOT", cmd
        }

        mockEc2Server.use {
            EC2Server ec2Server = new EC2Server()

            mockTomcatServer.demand.getHost { ec2Server }
            mockTomcatServer.demand.supportsExplodedWars { true }
            mockTomcatServer.demand.getDeploymentDirectory { "/usr/catalina.home/webapps" }

            mockS3Synchronizer.use {
                mockTomcatServer.use {
                    TomcatServer tomcatServer = new TomcatServer()
                    webApp.updateTomcat(tomcatServer, "")
                }
            }
        }
    }

    public void testUpdateWarNoRootExplodedS3Url() {
        WebApp webApp = new WebApp("s3://mybucket/myWebApp", "mycontext")

        mockEc2Server.demand.getAwsProperties { new AWSProperties(new Properties())}
        mockS3Synchronizer.demand.downloadFromS3 {host, bucketPrefix, bucket, dir ->
            assertEquals "mybucket", bucket
            assertEquals "/tmp/mybucket", dir
        }

        mockEc2Server.demand.ssh {cmd ->
            assertEquals "rsync --del -u -v -r  /tmp/mybucket/myWebApp/ /usr/catalina.home/webapps/mycontext", cmd
        }

        mockEc2Server.use {
            EC2Server ec2Server = new EC2Server()

            mockTomcatServer.demand.getHost { ec2Server }
            mockTomcatServer.demand.supportsExplodedWars { true }
            mockTomcatServer.demand.getDeploymentDirectory { "/usr/catalina.home/webapps" }

            mockS3Synchronizer.use {
                mockTomcatServer.use {
                    TomcatServer tomcatServer = new TomcatServer()
                    webApp.updateTomcat(tomcatServer, "")
                }
            }
        }
    }

    public void testUpdateUnexplodedWarS3Url() {
        Properties properties = new Properties()
        properties.setProperty("accessKey", "MyAccessKey")
        properties.setProperty("secretKey", "MySecretKey")
        AWSProperties awsProperties = new AWSProperties(properties)

        WebApp webApp = new WebApp("s3://mybucket/mywar.war", "foobar")

        2.times { mockEc2Server.demand.getAwsProperties { awsProperties } }
        

        mockEc2Server.demand.ssh {cmd, input ->
            assertEquals "rm -f .awssecret ; cat > .awssecret; chmod 0600 .awssecret", cmd
            assertEquals "MyAccessKey MySecretKey", input
        }

        mockEc2Server.demand.ssh {cmd ->
            assertEquals "s3get mybucket/mywar.war /usr/catalina.home/webapps/foobar.war", cmd
        }

        mockEc2Server.use {
            EC2Server ec2Server = new EC2Server()

            mockTomcatServer.demand.getHost { ec2Server }
            mockTomcatServer.demand.getDeploymentDirectory { "/usr/catalina.home/webapps" }

            mockS3Synchronizer.use {
                mockTomcatServer.use {
                    TomcatServer tomcatServer = new TomcatServer()
                    webApp.updateTomcat(tomcatServer, "")
                }
            }
        }
    }

    public void testUpdateWarNonS3Url() {
        WebApp webApp = new WebApp("/home/users/foo/myWebApp", "foo")

        mockEc2Server.demand.getAwsProperties { new AWSProperties(new Properties())}
        mockS3Synchronizer.demand.downloadFromS3 {host, bucketPrefix, bucket, dir ->
            assertEquals "somePrefix", bucketPrefix
            assertEquals "foo-tmp-war", bucket
            assertEquals "/tmp/foo-tmp-war", dir
        }

        mockEc2Server.demand.ssh {cmd ->
            assertEquals "rsync --del -u -v -r  /tmp/foo-tmp-war/myWebApp/ /usr/catalina.home/webapps/foo", cmd
        }

        mockEc2Server.use {
            EC2Server ec2Server = new EC2Server()

            mockTomcatServer.demand.getHost { ec2Server }
            mockTomcatServer.demand.supportsExplodedWars { true }
            mockTomcatServer.demand.getDeploymentDirectory { "/usr/catalina.home/webapps" }

            mockS3Synchronizer.use {
                mockTomcatServer.use {
                    TomcatServer tomcatServer = new TomcatServer()
                    webApp.updateTomcat(tomcatServer, "somePrefix")
                }
            }
        }
    }

    public void testUpdateWarNonS3UrlAsUnexplodedWar() {
        WebApp webApp = new WebApp("/home/users/foo/myWebApp", "foo")

        mockEc2Server.demand.getAwsProperties { new AWSProperties(new Properties())}
        mockS3Synchronizer.demand.downloadFromS3 {host, bucketPrefix, bucket, dir ->
            assertEquals "somePrefix", bucketPrefix
            assertEquals "foo-tmp-war", bucket
            assertEquals "/tmp/foo-tmp-war", dir
        }

        mockEc2Server.demand.ssh {cmd ->
            assertEquals "cd /tmp/foo-tmp-war/myWebApp; jar cf /tmp/foo.war . ; cp /tmp/foo.war /usr/catalina.home/webapps", cmd
        }

        mockEc2Server.use {
            EC2Server ec2Server = new EC2Server()

            mockTomcatServer.demand.getHost { ec2Server }
            mockTomcatServer.demand.supportsExplodedWars { false }
            mockTomcatServer.demand.getDeploymentDirectory { "/usr/catalina.home/webapps" }

            mockS3Synchronizer.use {
                mockTomcatServer.use {
                    TomcatServer tomcatServer = new TomcatServer()
                    webApp.updateTomcat(tomcatServer, "somePrefix")
                }
            }
        }
    }

    public void testUploadToS3() {
        WebApp webApp = new WebApp("/home/users/foo/myWebApp", "foo")

        mockS3Synchronizer.demand.uploadToS3 { wars, bucketPrefix, bucket ->
            assertEquals "myPrefix", bucketPrefix
            assertEquals (["/home/users/foo/myWebApp"], wars)
            assertEquals "foo-tmp-war", bucket
        }
        mockS3Synchronizer.use {
                webApp.uploadToS3(new AWSProperties(new Properties()), "myPrefix")
        }
    }

}